// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Diagnostics.Contracts; using System.Text; using System.Xml.Serialization; using LargoCommon.Abstract; namespace LargoCommon.Music { /// /// Figural Schema. /// public class FiguralSchema : FiguralStructure { #region Constructors /// Initializes a new instance of the FiguralSchema class. public FiguralSchema() { this.FormalBehavior = new FormalBehavior(); this.RhythmicBehavior = new RhythmicBehavior(); } /// /// Initializes a new instance of the FiguralSchema class. /// /// The given system. /// Structural code. public FiguralSchema(GeneralSystem givenSystem, string structuralCode) : base(givenSystem, structuralCode) { Contract.Requires(givenSystem != null); this.FormalBehavior = new FormalBehavior(); this.RhythmicBehavior = new RhythmicBehavior(); } /// /// Initializes a new instance of the FiguralSchema class. /// /// The given system. /// Number of instance. public FiguralSchema(GeneralSystem givenSystem, decimal number) : base(givenSystem, number) { Contract.Requires(givenSystem != null); this.FormalBehavior = new FormalBehavior(); this.RhythmicBehavior = new RhythmicBehavior(); } /// Initializes a new instance of the FiguralSchema class. /// Figural structure. public FiguralSchema(FiguralStructure structure) : base(structure) { Contract.Requires(structure != null); this.FormalBehavior = new FormalBehavior(); this.RhythmicBehavior = new RhythmicBehavior(); } #endregion #region Properties - Behavior /// /// Gets or sets the harmonic behavior. /// /// /// The harmonic behavior. /// public FormalBehavior FormalBehavior { get; set; } /// /// Gets or sets the harmonic behavior. /// /// /// The harmonic behavior. /// public RhythmicBehavior RhythmicBehavior { get; set; } #endregion #region Properties /// Gets order of system. /// Property description. public byte Order => this.GSystem.Order; /// Gets schema of elements. /// Property description. [XmlAttribute] public string ElementSchema { get { var s = this.ElementString(); return s?.Trim() ?? string.Empty; } } /// /// Gets a value indicating whether [zero start]. /// /// /// true if [zero start]; otherwise, false. /// public bool ZeroStart { get { var s = this.ElementSchema; return s.StartsWith("T", StringComparison.CurrentCulture) || s.StartsWith("X", StringComparison.CurrentCulture); } } #endregion #region Compute properties /// Evaluate and set Rhythmic properties . public void ComputeRhythmicProperties() { this.FormalBehavior.Variance = this.ComputeVariance(); this.FormalBehavior.Balance = this.ComputeBalance(); this.RhythmicBehavior.Filling = this.ComputeFilling(); this.RhythmicBehavior.Beat = this.ComputeBeat(); this.RhythmicBehavior.Mobility = this.ComputeMobility(); //// this.ComputeEntropy(); //// this.ComputeComplexity(); } /// /// Writes the behavior to properties. /// public override void WriteBehaviorToProperties() { if (this.FormalBehavior != null) { this.Properties[GenProperty.FormalBalance] = this.FormalBehavior.Balance; this.Properties[GenProperty.FormalVariance] = this.FormalBehavior.Variance; this.Properties[GenProperty.FormalEntropy] = this.FormalBehavior.Entropy; } if (this.RhythmicBehavior != null) { this.Properties[GenProperty.FormalFilling] = this.RhythmicBehavior.Filling; this.Properties[GenProperty.FormalBeat] = this.RhythmicBehavior.Beat; this.Properties[GenProperty.FormalMobility] = this.RhythmicBehavior.Mobility; this.Properties[GenProperty.FormalComplexity] = this.RhythmicBehavior.Complexity; } } #endregion #region Public methods /// Makes a deep copy of the FiguralSchema object. /// Returns object. public override object Clone() { return new FiguralStructure(this.GSystem, this.GetStructuralCode); } /// /// Returns inverted structure. /// /// Returns value. public FiguralSchema InvertedStructure() { var rs = new FiguralSchema { GSystem = this.GSystem }; for (byte i = 0; i < this.ElementList.Count; i++) { var value = (byte)this.ElementList[this.ElementList.Count - i - 1]; rs.ElementList.Add(value); } rs.CompleteFromElements(); rs.DetermineBehavior(); return rs; } #endregion #region String representation /// String representation of the object. /// Returns value. public override string ToString() { var s = new StringBuilder(base.ToString()); s.Append(" "); //// s.Append(this.DistanceString()); return s.ToString(); } #endregion #region Evaluation of properties /// Mean distance of nonzero bits. /// Returns value. protected float MeanDistance() { if (this.Level < 1) { return 1.0F; } // (float)Math.Pow(value, 1.0/Level); var value = this.GSystem.Order / (float)this.Level; return value; } /// /// Determine and sets the mobility property. /// /// Returns value. protected float ComputeMobility() { this.DetermineLevel(); float mobility = this.Level; //// float mobility = this.GSystem.Order > 0 ? (this.Level / (float)this.GSystem.Order) * 100f : 0; //// float mobility = this.GSystem.Order > 0 ? (this.ToneLevel / (float)this.GSystem.Order) * 100f : 0; //// var mobility = (this.ToneLevel / (float)this.Level) * 100f; return mobility; } /// /// Determine and sets the variance property. /// /// Returns value. protected float ComputeVariance() { // variational quotient var bst = this.BinaryStructure(false); //// 2015/01 var bs = new BinarySchema(bst); //// bs.ComputeRhythmicProperties(); var variance = bs.ComputeVariance(); //// bs.Variance; return variance; } /// /// Determine and sets the mobility property. /// /// Returns value. protected float ComputeFilling() { // float filling = ((float)Level/(float)GSystem.Order)*100f; var order = this.GSystem.Order; byte sum = 0; var hasFilling = false; for (byte e = 0; e < order; e++) { if (this.IsOn(e)) { if (this.IsPauseStart(e)) { hasFilling = false; } else { hasFilling = true; sum++; } } else { if (hasFilling) { sum++; } } } var filling = 100.0f * sum / order; return filling; } /// /// Determine and sets the side property. /// /// Returns value. protected float ComputeBalance() { var balance = 0f; if (this.Level > 0) { var median = this.GSystem.Median; if (median > 0) { float left = this.IsOnInRange(0, (byte)(median - 1)); float right = this.IsOnInRange(median, (byte)(this.GSystem.Order - 1)); balance = (DefaultValue.HalfUnit + ((right - left) / this.GSystem.Order)) * 100.0f; } } return balance; } /// /// Determine and sets the entropy property. /// /// Returns value. protected float ComputeEntropy() { var entropy = 0f; if (this.Level > 1) { const float value = 0.0f; //// for (byte lev = 0; lev < Level; lev++) {} var logLevel = (float)Math.Log(this.Level); if (logLevel >= DefaultValue.AfterZero && logLevel <= DefaultValue.LargeNumber) { entropy = -value / logLevel * 100f; } } return entropy; } /// /// Determine and sets the beat property. /// /// Returns value. protected float ComputeBeat() { var beat = 0F; if (this.Level > 0) { float v = 0, tv = 0; var order = this.GSystem.Order; for (byte m = 2; m < order; m++) { if (order % m != 0) { continue; } for (byte e = 0; e < order; e++) { if (e % m != 0) { continue; } float dv = m; if (this.IsOn(e) && !this.IsPauseStart(e)) { v += dv; } tv += dv; } } if (tv >= DefaultValue.AfterZero && tv <= DefaultValue.LargeNumber) { beat = v / tv * 100.0f; } } return beat; } #endregion } }